﻿using System;
using DeltaGroup.WheelOfJeopardy.Model;

namespace DeltaGroup.WheelOfJeopardy.GameManager
{
    using System.ComponentModel;
    using System.Configuration;

    using DeltaGroup.WheelOfJeopardy.Util;

    public class GameSettings : INotifyPropertyChanged, IDataErrorInfo, IGameSettings
    {
        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="GameSettings"/> class.
        /// </summary>
        public GameSettings()
        {
            Config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            AppSettings = Config.AppSettings.Settings;

            if (SpinsPerNormalRound <= 0)
                SpinsPerNormalRound = 50;
            if (EasyModeResponseTimeLimit <= 0)
                EasyModeResponseTimeLimit = 60;
            if (MediumModeResponseTimeLimit <= 0)
                MediumModeResponseTimeLimit = 45;
            if (HardModeResponseTimeLimit <= 0)
                HardModeResponseTimeLimit = 30;
        }

        #endregion Constructors

        #region Events

        /// <summary>
        /// Occurs when a property value changes.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        #endregion Events

        #region Properties

        /// <summary>
        /// Gets or sets a value indicating whether [debug mode].
        /// </summary>
        /// <value><c>true</c> if [debug mode]; otherwise, <c>false</c>.</value>
        public bool DebugMode
        {
            get { return AppSettings["DebugMode"].Value == "Y"; }
            set
            {
                AppSettings["DebugMode"].Value = value ? "Y" : "N";
                Config.Save(ConfigurationSaveMode.Modified);
                ConfigurationManager.RefreshSection("appSetting");
                FirePropertyChanged("DebugMode");
            }
        }

        public string Error
        {
            get { return null; }
        }

        /// <summary>
        /// Gets or sets the response time limit.
        /// </summary>
        /// <value>The response time limit.</value>
        public int HardModeResponseTimeLimit
        {
            get { return AppSettings["HardModeResponseTimeLimit"].Value.ToInt(); }
            set
            {
                AppSettings["HardModeResponseTimeLimit"].Value = value.ToString();
                Config.Save(ConfigurationSaveMode.Modified);
                ConfigurationManager.RefreshSection("appSetting");
                FirePropertyChanged("HardModeResponseTimeLimit");
            }
        }
        /// <summary>
        /// Gets or sets the response time limit.
        /// </summary>
        /// <value>The response time limit.</value>
        public int MediumModeResponseTimeLimit
        {
            get { return AppSettings["MediumModeResponseTimeLimit"].Value.ToInt(); }
            set
            {
                AppSettings["MediumModeResponseTimeLimit"].Value = value.ToString();
                Config.Save(ConfigurationSaveMode.Modified);
                ConfigurationManager.RefreshSection("appSetting");
                FirePropertyChanged("MediumModeResponseTimeLimit");
            }
        }
        /// <summary>
        /// Gets or sets the response time limit.
        /// </summary>
        /// <value>The response time limit.</value>
        public int EasyModeResponseTimeLimit
        {
            get { return AppSettings["EasyModeResponseTimeLimit"].Value.ToInt(); }
            set
            {
                AppSettings["EasyModeResponseTimeLimit"].Value = value.ToString();
                Config.Save(ConfigurationSaveMode.Modified);
                ConfigurationManager.RefreshSection("appSetting");
                FirePropertyChanged("EasyModeResponseTimeLimit");
            }
        }

        public int GetResponseTimeLimit(DifficultyLevel difficulty)
        {
            switch (difficulty)
            {
                case DifficultyLevel.Easy:
                    return EasyModeResponseTimeLimit;
                case DifficultyLevel.Medium:
                    return MediumModeResponseTimeLimit;
                case DifficultyLevel.Hard:
                    return HardModeResponseTimeLimit;
                default:
                    throw new ArgumentOutOfRangeException("difficulty");
            }
        }

        /// <summary>
        /// Gets or sets the spins per normal round.
        /// </summary>
        /// <value>The spins per normal round.</value>
        public int SpinsPerNormalRound
        {
            get { return AppSettings["SpinsPerJeopardy"].Value.ToInt(); }
            set
            {
                AppSettings["SpinsPerJeopardy"].Value = value.ToString();
                Config.Save(ConfigurationSaveMode.Modified);
                ConfigurationManager.RefreshSection("appSetting");
                FirePropertyChanged("SpinsPerNormalRound");
            }
        }

        /// <summary>
        /// Gets or sets the app settings.
        /// </summary>
        /// <value>The app settings.</value>
        private KeyValueConfigurationCollection AppSettings
        {
            get; set;
        }

        /// <summary>
        /// Gets or sets the config.
        /// </summary>
        /// <value>The config.</value>
        private Configuration Config
        {
            get; set;
        }

        #endregion Properties

        #region Indexers

        /// <summary>
        /// Gets the <see cref="System.String"/> with the specified column name.
        /// </summary>
        /// <value></value>
        public string this[string columnName]
        {
            get
            {
                switch (columnName)
                {
                    case "EasyModeResponseTimeLimit":
                        return EasyModeResponseTimeLimit < 1 ? "Time limit should be greater than 1" : null;
                    case "MediumModeResponseTimeLimit":
                        return MediumModeResponseTimeLimit < 1 ? "Time limit should be greater than 1" : null;
                    case "HardModeResponseTimeLimit":
                        return HardModeResponseTimeLimit < 1 ? "Time limit should be greater than 1" : null;
                    case "SpinsPerNormalRound":
                        return SpinsPerNormalRound < 1 ? "Number of spins must be at least 1" : null;
                    default:
                        return null;
                }
            }
        }

        #endregion Indexers

        #region Methods

        /// <summary>
        /// Fires the property changed.
        /// </summary>
        /// <param name="name">The name.</param>
        protected void FirePropertyChanged(string name)
        {
            if (PropertyChanged == null)
                return;

            PropertyChanged(this, new PropertyChangedEventArgs(name));
        }

        #endregion Methods
    }
}